perm filename MBOX.DGL[UP,DOC]2 blob sn#327379 filedate 1978-01-10 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00010 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	Abstract.
C00003 00003	FRM box output
C00006 00004	A little bit about loading FRM Event Lists into the SIX
C00009 00005	Samson box output
C00014 00006	Bells and whistles for MBOX output.
C00022 00007	Even less about loading Samson box command streams
C00034 00008	Loading your own instruments.
C00037 00009	GOSC GOSCVF SHAPE LINGER GEN MOD MIX RANDOM FILTER REV GENFM1 GENFM3
C00041 00010	That's about all you need to know.  If you have any questions, 
C00044 ENDMK
C⊗;
Abstract.

This describes the program MBOX, written by Gareth Loy,
which takes PLAY  block code suitable  for MUSCMP, such  as the output  of
SCORE or whatever and translates it  into either a binary command  stream
for the Samson box or an Event List for the FRM box.

The program is made to resemble  MUSCMP insofar as is possible, with  some
additions and changes, as the realtime instruments require.

Input can be done from a file, or from the console, as in MUSCMP;
FRM box output
A simple example should suffice  for FRM box code,  as at this point  it's
input is quite simple, it rigidly requires  that the begin time be in  P1,
duration in P2, and frequency in Hz in P3.  All other fields are  ignored.
The following is an input file for the FRM box:

	instrument Soprano,Alto;
	boxtyp←frmdev;
	 PLAY foo.pla;
	 Soprano      0.00     0.14 AS;
	 Soprano      0.15     1.00 B/2;
	 Alto         1.00     6.67 AS*2;
	 FINISH;
	exit;

The INSTRUMENT definition can be used to declare any number of instruments
(however the FRM box only  can handle 32).  At  the moment, they are  non-
reentrant instruments like in MUSCMP, however this will change shortly.

The statement  boxtyp←frmdev  makes MBOX  put  out an  Event  list.   That
statement wouldn't be necessary if the input file had the extension  .FRM,
which would also set boxtyp.
Boxtyp←samdev will switch the mode to Samson code (but don't change  boxes
in the middle of the stream!).

The output will go  to a file  FOO.PLA as specified  after the PLAY  block
declaration. (The .PLA extension is required for Event Lists.)  Three notes
will be  played as  indicated.  Notice that the two Soprano notes cannot sound
simultaneously in FRM code (for now).
The  EXIT command  is optional,  and  just
forces the program to  quit instead of asking  for more input.  Here's  an
example of running the file:

.r mbox

FILE:    foo.frm
	Reading input file:	DSK:FOO.FRM[SAM,DGL]
	Command output to file:		DSK:FOO.PLA[SAM,DGL]
	Finishing command output file	DSK:FOO.PLA[SAM,DGL]

End of SAIL execution

↑C
.
A little bit about loading FRM Event Lists into the SIX
Once you've got your Event List, do the following:
Find some program with .RTJ as  an extension on [FRM,MUS] that produces  a
timbre and has at least as many voices as you want.  These files are  FAIL
code, and the Event Lists are macros that are loaded into the code when it
is compiled.  The whole thing is then loaded into the SIX, which runs  the
code as a real time job, grabbing the FRM and passing it commands.  If  no
.RTJ program exists which suits your taste and or number of voices, you'll
have to hack around inside one of  them yourself, which works only if  you
know FAIL.
For example, to synthesize the example of FRM code on the previous  pages,
I (with Dick's help) created an  .RTJ file called FANFA.RTJ which has  two
trumpets with the unlikely names of Soprano and Alto (strumpets?!?).  Then
I compiled a copy of this master FAIL file into a dump that contained also
the Event List:

.al frm,mus
.Load foo←fanfa.rtj/compile/save

Somwhere along the way the FAIL compiler  asked me to type in the name  of
the .PLA file containing the Event List, and I typed, exactly:

file foo.pla <meta> <control> <linefeed>

The .PLA file must be on  FRM,MUS, the FAIL compiler aparently can't  find
other areas.  When  compilation and loading  were done, then  to hear  the
score type:

.ru ten

then enter the  dump file  for the RTJ  and follow  directions (Fire  when
ready Gridly!).
Samson box output
Here's an  example  of  getting  Samson  box  output.   It's  a  bit  more
complicated by virtue of  being more controllable.  There  is code for
Samson instruments predeclared  in MBOX  which you assign  names with  the
INSTRUMENT command (see note below). 
They perform a variety of simple functions such as sinusoid generation,
fm, filtering, reverb, etc.  See the description of the default instruments
in appendix ∃.
They are able to use functions created by
Andy's SEG  record generating program,  SYS:TFUN (If  you
don't know about  this, some documentation is available in INTERM.TXT[DOC,MUS],
under the subject of FUNED and EDFUN, there is also in the program itself.)
Unlike MUSCMP (that is, NEWMUS and MUSIC and friends) the
instruments can be  reentered.  What happens  is that MBOX  sprouts a  new
instrument of the same class  if one like it  was already running.  To  be
specific, overlapping the same instrument with itself will work (up to the
limit of  the  Samson box  hardware  = 256  oscillators,  128  modifiers).
Here's an input file:

	instrument Gosc Soprano,Alto;
	record test;
	 PLAY foo;
	 Soprano      0.00     0.14 AS test1 1 0 a_running+lplusq+sine 0 zero outa;
	 Soprano      0.00     1.14 B/2;
	 Alto         1.00     6.67 AS*2;
	 FINISH;
	exit;

The only formal addition is that of the RECORD declaration.  The argument to that
command is the  name of a  file with  an assumed extension  of .FUN  which
contains SEG type record functions created by Andy's TFUN program.   There
were two records in  the file TEST.FUN when  this example was made  called
Test1 and Test.  Each described  a typical amplitude function that
ranged between 0 and 1.  These  are
then included in the instrument calls just the way that, for instance,  F1
would be passed to a MUSCMP instrument. 
	The other funny things are as follows: p5 is a scaling term for
the record, p6 is a d.c. offset term for the record, next comes the running
mode (see LRNSAM.DGL[UP,DOC] for details), followed by the fm input term
(here set to read from a predeclared location that returns zeros only) and
finally the sum memory location that the whole thing writes into.

This file ran  as follows:

r mbox

FILE:    foo
	Reading input file:	DSK:FOO.SAM[SAM,DGL]
	Reading Func file: DSK:TEST.FUN[SAM,DGL]
	Record list: TEST1 TEST
	Command output to file:		DSK:FOO.doa[SAM,DGL]
PFINISH: Scheduling statistics:
Number of waits = 20, Max Q len = 3
Average Q len = 2
	Finishing command output file	DSK:FOO.doa[SAM,DGL]

End of SAIL execution

↑C

**********
NOTE:  It is possible to make up your own Samson instruments and load
them with MBOX.  To do this is not difficult, but requires more explanation
than I care to go into here.  See me.  Whenever Mark Kahrs finishes
writing a Lisp Loader for me, it will be possible to load in instruments
at run time with the Instrument declaration.
Bells and whistles for MBOX output.

User settable variables to set before entering PLAY block:
	The following variables are tested by MBOX when it scanns a PLAY
statement to set overall conditions.  To have any effect, therefore, they
must be set before issuing the PLAY statement.
------------------------------------------------------------------------
boxtyp		assign either samdev or frmdev to determine the type of
		output, defaults to samdev.  This is also settable by
		having your input file have either extensions .SAM
		or .FRM respectively;
nptix		assign to how many processing ticks, defaults to 32;
nutix		assign to how many update ticks, defaults to 96;
noutchans	assign between 0 and 4 output channels,
		defaults to quad;
whichside	assign 0 for dacs to read from generator sum memory only, 
		positive for modifier side only, negative for both sides,
		defaults to negative;
filters		for low pass filters on the dacs, assign any of these values:
			"unfiltered" ≡ bypass analog filters,
			0 ≡ 4.5 kHz
			1 ≡ 9.0 kHz
			2 ≡ 13.5 kHz
			3 ≡ 18.0 kHz,
		defaults to 3;
packing		set to left_justified, right_justified or full_word,
		defaults to full_word which is interpreted by LOWER to
		only load full_word when necessary;
optimization	set to optimize or non_optimize to determine whether
		LOWER will pack more commands per word where possible,
		defaults to non_optimize (this may change);
debug		assign with any summation of
		debug_instruments	to see what values they are passed,
		debug_scanning		to see what is read in from a file,
		debug_arithmetic	to see how MBOX does it's arithmetic,
		debug_stack		to see the contents of arithmetic stacks,
		debug_scheduling	to see how MBOX sprouts instruments;
************************************************************************

Variables preset by MBOX:
	All of the following are set up when you issue a PLAY statement.
They will not be assigned actual values until then!  These are writable
variables, so if you want to clobber them you can.  No guarentees, however
that doing so will get you anywhere.
------------------------------------------------------------------------
zero		predeclared sum memory location to always return zero;
srate		will contain sampling rate calculated from nptix and nutix;
mag		will have frequency scalling calculated from srate;
outa, outb...d  predeclared sum memory locations to stuff generator output;
outma, outmb..d predeclared sum memory locations to stuff modifier output;
************************************************************************

Reserved procedures in MBOX:
	These claim and return the address of the next free sum memory 
location. They require initialization induced by the PLAY statement, and their
results are invalid outside a PLAY block.
------------------------------------------------------------------------
gen_sum		returns the next free last pass sum memory location;
mod_sum		likewise for modifiers;
************************************************************************

Preloaded variables:
	These variables are set up when MBOX is entered and are valid
anywhere.  They are assigned the values indicated below them.
------------------------------------------------------------------------
A,AS,B,C,CS,D,DS,E,F,FS,G,GS;
440,466.16,493.89,261.62,277.18,293.66,311.13,329.63,349.23,369.99,391.99,415.31;
************************************************************************

Symbolic constants:
	These are predeclared symbols.  They cannot be assigned to,
but may be assigned from (e.g. a←pi, but not pi←a).
-------------------------------------------------------------------------
Generators:
g_inactive, g_pause, a_running, b_running, g_wait, c_running,
data_read, data_write, dac_write,
lplusq, lminusq, lexpplus, lexpminus,
sum_of_cosines, sawtooth, square, pulse_train, sine, sin_fm;

Modifiers:
m_inactive, u_noise, tr_u_noise, latch, threshold, invoke_delay_unit,
notwopoles, two_0poles, two_1poles,
notwozeroes, two_0zeroes, two_1zeroes,
int_mixing, one_pole, mixing, one_zero,
four_quad_multiply, am,
maximum, minimum, signum, zero_crossing_pulser,
add_sum_memory, replace_sum_memory;

Delay units:
delay, 
d_inactive,
delayline, table_lookup, round_table_lookup;

Debugging:
debug_instruments, debug_arithmetic, debug_scheduling, debug_scanning,
debug_stack,debug_records,debug_template;

Initialization:
samdev,frmdev,
unfiltered,
optimize,non_optimize,
right_justified,left_justified,full_word;

Misc. commands:
pause_clear,wait_clear;

Constants:
pi,
true,false;
************************************************************************
Even less about loading Samson box command streams
There are two things you can do with the output of MBOX (that I know of)
namely disassemble it to see if it looks reasonable, or play it to
see if it sounds reasonable.
	Playing the commands currently requires that you make up a realtime
job to be loaded on the SIX that actually runs SAM.  The best way to do this
is to not ask any questions, but to make a do file called something
like CVSND.DO that looks like this:

ru cvos↔?a.doa↔?a.str↔loa ?a←rehead.rtj+?a.str+tail.rtj↔r ten↔?a↔

Then you need the sources of the things the do file will call.  So copy into
your area the following files:
	cvos.dmp[sam,mus],
	rehead.rtj[sam,dgl],
	tail.rtj[sam,dgl].

Then type to the monitor:
.DO CVSND
to which it will respond:
  a=	_
to which you respond (in this case):
foo<cr>
It will then go away and print various things on your screen and eventually
come back to ask you to type <cr> to start job.  Do so and follow instructions.
Typing <alt> will exit this program.

	Disassembly is done with
Mark Kahrs' program DAB (a lil' dab'l do ya') which stands for 
DisAssemble the Box.
You take the command file, in this case FOO.doa, and

.r dab
input file: foo.doa
output file: foo.dab

↑C
.
et foo.dab/r

and this is what you get (egads!):

0       20000005001     GFM     0           1               ;fm address
1       15401           GO      1           1               ;sweep rate
2       10400005001     GMODE   200         1               ;mode dac l+q sum
3       1400600         HiProc  140                         ;Highest Proc Tick
4       2000610         HiTick  200                         ;Highest Tick
5       10000005002     GMODE   0           2               ;mode inactive l+q sum
6       20000004002     GSUM    0           2               ;sum memory
7       5402            GO      0           2               ;sweep rate
8       314022002       GJr     31402       2               ;frequency
9       20000005002     GFM     0           2               ;fm address
10      10000004002     GL      0           2               ;asymptote
11      1002            GQr     0           2               ;decay exponent
12      3002            GP      0           2               ;delta
13      4402            GK      0           2               ;angle
14      20000003402     GM      0           2               ;scale
15      10000003402     GN      0           2               ;ncosines
16      13610005002     GMODE   1704        2               ;mode a_run l+q cos
17      10000005003     GMODE   0           3               ;mode inactive l+q sum
18      20000004003     GSUM    0           3               ;sum memory
19      5403            GO      0           3               ;sweep rate
20      154052003       GJr     15405       3               ;frequency
21      20000005003     GFM     0           3               ;fm address
22      10000004003     GL      0           3               ;asymptote
23      1003            GQr     0           3               ;decay exponent
24      3003            GP      0           3               ;delta
25      4403            GK      0           3               ;angle
26      20000003403     GM      0           3               ;scale
27      10000003403     GN      0           3               ;ncosines
28      13610005003     GMODE   1704        3               ;mode a_run l+q cos
29      3002            GP      0           2               ;delta
30      1002            GQr     0           2               ;decay exponent
31      3003            GP      0           3               ;delta
32      1003            GQr     0           3               ;decay exponent
33      6070420         Dwell   607                         ;Dwell (Linger)
34      3002            GP      0           2               ;delta
35      20550420        Dwell   2055                        ;Dwell (Linger)
36      3002            GP      0           2               ;delta
37      60400420        Dwell   6040                        ;Dwell (Linger)
38      3002            GP      0           2               ;delta
39      61640420        Dwell   6164                        ;Dwell (Linger)
40      3003            GP      0           3               ;delta
41      105550420       Dwell   10555                       ;Dwell (Linger)
42      3002            GP      0           2               ;delta
43      121700420       Dwell   12170                       ;Dwell (Linger)
44      3002            GP      0           2               ;delta
45      1002            GQr     0           2               ;decay exponent
46      210070420       Dwell   21007                       ;Dwell (Linger)
47      3003            GP      0           3               ;delta
48      613010420       Dwell   61301                       ;Dwell (Linger)
49      3003            GP      0           3               ;delta
50      1067500420      Dwell   106750                      ;Dwell (Linger)
51      3003            GP      0           3               ;delta
52      10000005004     GMODE   0           4               ;mode inactive l+q sum
53      20000004004     GSUM    0           4               ;sum memory
54      5404            GO      0           4               ;sweep rate
55      630042004       GJr     63004       4               ;frequency
56      20000005004     GFM     0           4               ;fm address
57      10000004004     GL      0           4               ;asymptote
58      1004            GQr     0           4               ;decay exponent
59      3004            GP      0           4               ;delta
60      4404            GK      0           4               ;angle
61      20000003404     GM      0           4               ;scale
62      10000003404     GN      0           4               ;ncosines
63      13610005004     GMODE   1704        4               ;mode a_run l+q cos
64      1110700420      Dwell   111070                      ;Dwell (Linger)
65      3004            GP      0           4               ;delta
66      1004            GQr     0           4               ;decay exponent
67      1232600420      Dwell   123260                      ;Dwell (Linger)
68      3003            GP      0           3               ;delta
69      1003            GQr     0           3               ;decay exponent
70      1554270420      Dwell   155427                      ;Dwell (Linger)
71      3004            GP      0           4               ;delta
72      2545240420      Dwell   254524                      ;Dwell (Linger)
73      3004            GP      0           4               ;delta
74      5520130420      Dwell   552013                      ;Dwell (Linger)
75      3004            GP      0           4               ;delta
76      7502050420      Dwell   750205                      ;Dwell (Linger)
77      3004            GP      0           4               ;delta
78      10606000420     Dwell   1060600                     ;Dwell (Linger)
79      3004            GP      0           4               ;delta
80      1004            GQr     0           4               ;decay exponent
81      0               Noop                                ;Misc No effect
Loading your own instruments.
(This is currently under development, sorry for the inconvienience,
I hope construction will be done shortly, but meanwhile, pardon
my dirt!)

	Currently there is only one way to do this, by using
the system loader to load in your instruments with the MBOX scanner.

MBOX figures out from the INSTRUMENT statement what template
to associate with what set of instrument names.  The template
name in the INSTRUMENT definition is matched up against a list of
preloaded template names, and the right instrument template procedure
(the one that does the actual stuffing of commands) is called
by using the number of the array element where this template name
is found in the template table.  It takes this number and uses
it in a case statement to figure out which procedure to call.
The actual calling of the procedure is done in InsCal.
The names of the procedures in the InsCal case statement are named
Ins0 through Ins17.
	If you don't want to use the predeclared instrument template
names (likely, if you are rolling your own) then you can overwrite
the default names using the TEMPLATE declaration.  The set of
names following the declaration will then become the only template
names available and they will be matched up starting from
Ins0.

Your instrument template should look like this:
	(color this in SAIL)

GOSC GOSCVF SHAPE LINGER GEN MOD MIX RANDOM FILTER REV GENFM1 GENFM3
These are the formal calls to the instruments that are preloaded in MBOX.

∂ GOSC - fixed frequency, seg record variable amplitude;

∂ sample call:
    <instrument> Beg, Dur, Freq, ampRec, Ampscl, Ampoff, Mod, Ncs, Fmsum, outsum;

∂ GOSCVF - seg record variable frequency and amplitude;

∂ Sample call in an MBOX play list:
    <instrument>, beg, dur, frqRec, Frscl, Froff, ampRec, Ampscl, Ampoff,
    Mod, Ncs, Fmsum, Outsum;

∂ SHAPE - apply an envelope to a signal of amp up to 8.0;

∂ Sample call:
    <instrument> beg,dur,ampRec,scale,offset,outadr,inadr,factor;

∂ LINGER;

∂ sample call:
    <instrument> beg dur;

∂ GEN - raw call to a generator, with scaling of frq and sum_of_cosines;

∂ sample call:
    <instrument> Beg, Dur, Freq, Sweep, Angle, nCos, Scale, 
    Asym, Rate, Exp, Mod, Fmsum, Outsum, GenNum;
∂ Some things, but not many, are done for you here:
	1. Frq is scaled by mag.
	2. If Scale is 0, calculate Scale from nCos.
	3. If GenNum>0 then claim that generator, else take first available.
;
∂ MOD - raw call to a modifier, no scaling of any terms;

∂ sample call:
    <instrument> beg dur cf0 cf1 trm0 trm1 ain bin outloc ascl bscl mode modnum;
    ∂ If modnum>0 then claim that modifier, else take the first that's available;

∂ MIX - Multiply two signals by a constant factors between 0 and 8.

∂ sample call:
    <instrument> beg dur factor1 factor2 in1loc in2loc outloc;

∂ RANDOM - Make random numbers scaled by a factor;

∂ sample call:
    <instrument> beg dur factor trigger seed outloc;

∂ FILTER - Does one or two pole or zero fixed character filtering.

∂ sample call:
    <instrument> beg dur frq R second_order all_pole inloc outloc;

∂ REV - Reverberator. Can be all-pass or comb.
To make an allpass, set g1←-g0←G;

∂ sample call:
    <instrument> beg dur length g0 g1 inloc outloc;

∂ GENFM1;

∂ sample call:
    <instrument> Beg, Dur, Freq, ampRec, Ampscl, Ampoff, 
    Mode, Ncs, cfmfRatio, indexRec, index, indexOff, outsum;

∂ GENFM3;

∂ sample call:
    <instrument> Beg, Dur, Freq, ampRec, Ampscl, Ampoff, Mode, Ncs, 
    cfmfRatio1, indexRec1, index1, indexOff1,
    cfmfRatio2, indexRec2, index2, indexOff2,
    cfmfRatio3, indexRec3, index3, indexOff3,
    outsum;

That's about all you need to know.  If you have any questions, 

I just stepped out...